package company.huawei.pro;

import java.util.ArrayList;
import java.util.List;

/**
 * @author LiangMu
 * @version \$Id: Main3.java, v 0.1, 2022年08月14日 2:55 下午 LiangMu Exp $$
 */
public class Main3 {
    /**
     * https://leetcode.cn/problems/fraction-addition-and-subtraction
     * 给定一个表示分数加减运算的字符串 expression ，你需要返回一个字符串形式的计算结果。 
     * <p>
     * 这个结果应该是不可约分的分数，即最简分数。 如果最终结果是一个整数，例如 2，你需要将它转换成分数形式，其分母为 1。所以在上述例子中, 2 应该被转换为 2/1。
     * <p>
     *  
     * <p>
     * 示例 1:
     * <p>
     * 输入: expression = "-1/2+1/2"
     * 输出: "0/1"
     * <p>
     * "-1/2+1/3" - 1/2 + 1/3 -1/2 +1/3
     * class mark 1 -1
     * t 1
     * b 2
     * new Num(-1, 1, 2) = Num(-1, 3, 6)
     * new Num(1, 1, 3) = Num(1, 2, 6)
     * -1 * 3 + 1 * 2 = t
     * 4 / 6  == 2 / 3
     * 10 / 6 == 5 / 3
     * <p>
     * 10 6
     * fori - 6 i = 2
     * fun2
     */
    public static void main(String[] args) {
        String fun = fun("-1/2+1/2");
        System.out.println(fun);
    }

    public static String fun(String express) {
        char[] chars = express.toCharArray();
        List<Character> marks = new ArrayList<>();
        marks.add('+');
        marks.add('-');
        List<Num> nums = new ArrayList<>();
        Num num = null;
        boolean b = Boolean.TRUE;
        for (char item : chars) {
            if (marks.contains(item)) {
                if (item == '-') {
                    num = new Num(-1);
                } else {
                    num = new Num(1);
                }
                b = Boolean.TRUE;
                nums.add(num);
            } else if (item == '/') {
                b = Boolean.FALSE;
            } else {
                if (num == null) num = new Num(1);
                if (b) {
                    int i = num.getT() * 10 + Integer.parseInt(String.valueOf(item));
                    num.setT(i);
                } else {
                    int i = num.getB() * 10 + Integer.parseInt(String.valueOf(item));
                    num.setB(i);
                }
            }
        }
        return compute(nums);
    }

    static String compute(List<Num> nums) {
        if (nums.size() <= 0) return "1/1";
        int bottom = nums.stream().mapToInt(Num::getB).reduce(1, (a, b1) -> a * b1);
        nums.forEach(item -> {
            int b = item.getB();
            int t = bottom / b;
            item.setB(bottom);
            item.setT(t * item.getT());
        });
        // 计算
        int sum = 0;
        for (Num item : nums) {
            int temp = item.getT() * item.getMark();
            sum += temp;
        }
        String start = sum < 0 ? "-" : "";
        return start + fun2(sum, bottom);
    }

    static String fun2(int a, int b) {
        if (a == 0) return "0/1";
        a = Math.abs(a);
        for (int i = 2; i <= a; i++) {
            if (a % i == 0 && b % i == 0) {
                return fun2(a / i, b / i);
            }
        }
        return a + "/" + b;
    }

    static class Num {
        int t;
        int b;
        int mark = 1; // -1

        public void flex(int num) {
            t *= num;
            b *= num;
        }

        public Num(int mark) {
            this.mark = mark;
        }

        /**
         * Setter method for property t.
         *
         * @param t value to be assigned to property t
         */
        public void setT(int t) {
            this.t = t;
        }

        /**
         * Setter method for property b.
         *
         * @param b value to be assigned to property b
         */
        public void setB(int b) {
            this.b = b;
        }

        /**
         * Getter method for property t.
         *
         * @return property value of t
         */
        public int getT() {
            return t;
        }

        /**
         * Getter method for property b.
         *
         * @return property value of b
         */
        public int getB() {
            return b;
        }

        /**
         * Getter method for property mark.
         *
         * @return property value of mark
         */
        public int getMark() {
            return mark;
        }
    }
}
